package com.sms.service.impl;

import com.sms.exception.DataFileCorruptedException;
import com.sms.exception.SMSException;
import com.sms.model.Score;
import com.sms.service.ScoreService;
import com.sms.util.FileUtil;
import com.sms.util.ValidateUtil;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static com.sms.constants.SystemConstants.SCORE_FILE;

public class ScoreServiceImpl implements ScoreService {
    private static final DecimalFormat DF = new DecimalFormat("#.##");

    @Override
    public void addScore(Score score) throws SMSException, DataFileCorruptedException {
        // 参数校验
        if (score == null) {
            throw new SMSException("成绩对象不能为null");
        }

        if (!score.isValid()) {
            throw new SMSException("成绩数据无效！");
        }

        try {
            // 检查文件是否存在
            FileUtil.createFileIfNotExists(SCORE_FILE);

            // 检查成绩是否已存在
            List<Score> scores = FileUtil.loadScores(SCORE_FILE);
            boolean exists = scores.stream()
                    .anyMatch(s -> s.getStudentId().equals(score.getStudentId())
                            && s.getCourseId().equals(score.getCourseId()));

            if (exists) {
                throw new SMSException("该学生此课程成绩已存在");
            }

            // 追加写入文件
            FileUtil.writeLines(SCORE_FILE, List.of(score.toFileString()), true);
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public boolean updateScore(String studentId, String courseId, double newScore)
            throws SMSException, DataFileCorruptedException {

        // 参数校验
        if (!ValidateUtil.isValidStudentId(studentId)) {
            throw new SMSException("学号格式错误");
        }

        if (!ValidateUtil.isValidCourseId(courseId)) {
            throw new SMSException("课程ID格式错误");
        }

        if (!ValidateUtil.isValidScore(newScore)) {
            throw new SMSException("成绩必须在0-100之间");
        }

        try {
            // 读取所有成绩
            List<Score> scores = FileUtil.loadScores(SCORE_FILE);

            // 查找并更新
            boolean updated = false;
            for (Score score : scores) {
                if (score.getStudentId().equals(studentId)
                        && score.getCourseId().equals(courseId)) {
                    score.setScore(newScore);
                    updated = true;
                    break;
                }
            }

            if (!updated) {
                return false;
            }

            // 保存回文件
            FileUtil.writeLines(SCORE_FILE,
                    scores.stream().map(Score::toFileString).collect(Collectors.toList()));

            return true;
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public boolean deleteScore(String studentId, String courseId)
            throws DataFileCorruptedException {

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(SCORE_FILE)) {
                return false;
            }

            // 读取所有成绩
            List<Score> scores = FileUtil.loadScores(SCORE_FILE);

            // 删除指定成绩
            boolean removed = scores.removeIf(s ->
                    s.getStudentId().equals(studentId) && s.getCourseId().equals(courseId));

            if (!removed) {
                return false;
            }

            // 保存回文件
            FileUtil.writeLines(SCORE_FILE,
                    scores.stream().map(Score::toFileString).collect(Collectors.toList()));

            return true;
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public Score getScore(String studentId, String courseId)
            throws DataFileCorruptedException {

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(SCORE_FILE)) {
                return null;
            }

            // 读取所有成绩
            List<Score> scores = FileUtil.loadScores(SCORE_FILE);

            // 查找指定成绩
            return scores.stream()
                    .filter(s -> s.getStudentId().equals(studentId)
                            && s.getCourseId().equals(courseId))
                    .findFirst()
                    .orElse(null);
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public List<Score> getScoresByStudent(String studentId)
            throws DataFileCorruptedException {

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(SCORE_FILE)) {
                return List.of();
            }

            // 读取并过滤成绩
            return FileUtil.loadScores(SCORE_FILE).stream()
                    .filter(s -> s.getStudentId().equals(studentId))
                    .sorted(Comparator.comparing(Score::getCourseId))
                    .collect(Collectors.toList());
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public List<Score> getScoresByCourse(String courseId)
            throws DataFileCorruptedException {

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(SCORE_FILE)) {
                return List.of();
            }

            // 读取并过滤成绩
            return FileUtil.loadScores(SCORE_FILE).stream()
                    .filter(s -> s.getCourseId().equals(courseId))
                    .sorted(Comparator.comparing(Score::getStudentId))
                    .collect(Collectors.toList());
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public List<Score> getAllScores() throws DataFileCorruptedException {
        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(SCORE_FILE)) {
                return List.of();
            }

            // 读取所有成绩
            return FileUtil.loadScores(SCORE_FILE);
        } catch (IOException e) {
            throw new DataFileCorruptedException("成绩数据文件操作失败: " + e.getMessage());
        }
    }

    @Override
    public double calculateStudentAverage(String studentId)
            throws SMSException, DataFileCorruptedException {

        List<Score> scores = getScoresByStudent(studentId);

        if (scores.isEmpty()) {
            throw new SMSException("该学生没有成绩记录");
        }

        double sum = scores.stream().mapToDouble(Score::getScore).sum();
        return Double.parseDouble(DF.format(sum / scores.size()));
    }

    @Override
    public double calculateCourseAverage(String courseId)
            throws SMSException, DataFileCorruptedException {

        List<Score> scores = getScoresByCourse(courseId);

        if (scores.isEmpty()) {
            throw new SMSException("该课程没有成绩记录");
        }

        double sum = scores.stream().mapToDouble(Score::getScore).sum();
        return Double.parseDouble(DF.format(sum / scores.size()));
    }

    @Override
    public List<Score> getTopNStudents(int n, String courseId)
            throws DataFileCorruptedException {

        List<Score> scores = getScoresByCourse(courseId);

        return scores.stream()
                .sorted(Comparator.comparingDouble(Score::getScore).reversed())
                .limit(n)
                .collect(Collectors.toList());
    }
}